﻿using System;
using System.Collections.Generic;
using System.Xml.Linq;
using CPN.PJN.Silverlight.Common.Configuration;


namespace CPN.PJN.Silverlight.Common.ExceptionHandling.Configuration
{
    /// <summary>
    /// Cette classe permet de configurer le gestionnaire d'Exceptions
    /// </summary>
    public sealed class ExceptionConfigurationManager
    {
        #region Private Members

        /// <summary>
        /// Instance du Gestionnaire de configuration d'exception
        /// </summary>
        private static volatile ExceptionConfigurationManager instance;

        /// <summary>
        /// Objet de synchronisation
        /// </summary>
        private static object syncRoot = new Object();

        #endregion

        #region Instance Property

        /// <summary>
        /// Propriété Instance du Gestionnaire de configuration d'exception
        /// </summary>
        public static ExceptionConfigurationManager Instance
        {
            get
            {
                if (instance == null)
                {
                    lock (syncRoot)
                    {
                        if (instance == null)
                            instance = new ExceptionConfigurationManager();
                    }
                }

                return instance;
            }
        }

        #endregion

        #region PolicyDictionary Property

        /// <summary>
        /// Dictionnaire des politiques d'exceptions
        /// </summary>
        public Dictionary<string, ExceptionPolicy> PolicyDictionary { get; private set; }

        #endregion

        #region Private Constructor

        /// <summary>
        /// Constructeur privé
        /// </summary>
        private ExceptionConfigurationManager()
        {
            this.PolicyDictionary = new Dictionary<string, ExceptionPolicy>();
        }

        #endregion


        #region Configure Method

        /// <summary>
        /// Cette méthode permet de configuration les politiques d'Exception
        /// </summary>
        public void Configure()
        {
            this.ParseConfiguration(ConfigurationManager.Instance.ContentConfiguration);
        }

        #endregion

        #region ParseConfiguration Method

        /// <summary>
        /// Cette méthode permet de traiter les données
        /// </summary>
        /// <param name="data">donnée du fichier de configuration</param>
        private void ParseConfiguration(XElement dataElement)
        {
            try
            {
                if (dataElement.Elements("ExceptionConfiguration") != null)
                {
                    this.PolicyDictionary.Clear();

                    foreach (XElement policy in dataElement.Elements("ExceptionConfiguration").Descendants("ExceptionPolicy"))
                    {
                        var exceptionPolicy = new ExceptionPolicy();
                        if (policy.Attribute("name") != null)
                        {
                            exceptionPolicy.Name = policy.Attribute("name").Value;
                            exceptionPolicy.NotifyRethrow = string.IsNullOrEmpty(policy.Attribute("notifyRethrow").Value) || Convert.ToBoolean(policy.Attribute("notifyRethrow").Value) ? true : false;
                            foreach (XElement handler in policy.Descendants("ExceptionHandler"))
                            {

                                if (handler.Attribute("type") != null)
                                {
                                    var nameType = handler.Attribute("type").Value;
                                    var type = Type.GetType(nameType);
                                    if (type != null)
                                    {
                                        var implHandler = Activator.CreateInstance(type) as ExceptionHandler;
                                        if (implHandler != null)
                                        {
                                            if (handler.Attribute("name") != null)
                                            {
                                                implHandler.Name = handler.Attribute("name").Value;
                                                implHandler.Configure(handler);
                                                exceptionPolicy.ExceptionHandlerCollection.Add(implHandler);
                                            }
                                        }
                                    }
                                }
                            }
                        }

                        // Ajout de la Politique d'Exception
                        this.PolicyDictionary.Add(exceptionPolicy.Name, exceptionPolicy);
                    }
                }
            }
            catch (Exception)
            {
                throw;
            }
        }

        #endregion
    }
}
